﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.Diagnostics;
using GestureLib;
using WiimoteLib;
using System.Threading;

namespace PowerPointController
{
    public partial class OptionsForm : Form
    {
        private bool _isTrayClosing = false;

        private PowerPoint.Application _powerPointApplication;
        private GestureLib.GestureLib _gestureLib;
        private Wiimote _wiimote;

        public OptionsForm()
        {
            InitializeComponent();
        }

        private void OptionsForm_Load(object sender, EventArgs e)
        {
            _powerPointApplication = new PowerPoint.Application();
            _gestureLib = new GestureLib.GestureLib();

            _gestureLib.GestureDevice = CreateAndGetWiiDevice();

            #region Register Hotkey
            GlobalHotkeyHandler gh = new GlobalHotkeyHandler(this);
            gh.RegisterGlobalHotKey(Keys.M, GlobalHotkeyHandler.Modifiers.Control | GlobalHotkeyHandler.Modifiers.Alt);
            gh.HotkeyPressed += new EventHandler(GlobalHotKeyHandler_HotkeyPressed);
            #endregion

            #region Create Algorithms
            IGestureAlgorithm shakingTopBottom = new ShakingTopBottomGestureAlgorithm();
            IGestureAlgorithm shakingLeftRight = new ShakingLeftRightGestureAlgorithm();
            IGestureAlgorithm roll = new RollGestureAlgorithm();
            IGestureAlgorithm jab = new JabGestureAlgorithm();
            IGestureAlgorithm pitch = new PitchGestureAlgorithm();
            #endregion 

            #region Create Actions Gestures
            PowerPointSlideViewAction slideNext = new PowerPointSlideViewAction()
            {
                 Action = PowerPointSlideViewAction.SlideAction.NextSlide,
                 PowerPointApplication = _powerPointApplication
            };

            PowerPointSlideViewAction slidePrevious = new PowerPointSlideViewAction()
            {
                Action = PowerPointSlideViewAction.SlideAction.PreviousSlide,
                PowerPointApplication = _powerPointApplication
            };

            PowerPointSlideViewAction slideLast = new PowerPointSlideViewAction()
            {
                Action = PowerPointSlideViewAction.SlideAction.LastSlide,
                PowerPointApplication = _powerPointApplication
            };

            PowerPointSlideViewAction slideFirst = new PowerPointSlideViewAction()
            {
                Action = PowerPointSlideViewAction.SlideAction.FirstSlide,
                PowerPointApplication = _powerPointApplication
            };

            PowerPointSlideViewAction slideExit = new PowerPointSlideViewAction()
            {
                Action = PowerPointSlideViewAction.SlideAction.Exit,
                PowerPointApplication = _powerPointApplication
            };
            #endregion

            #region Create Trained Gestures
            TrainedGesture nextSlideGesture = new TrainedGesture();
            nextSlideGesture.GestureActions.Add(slideNext);
            nextSlideGesture.GestureAlgorithms.Add(shakingTopBottom);
            nextSlideGesture.Name = "NextSlideGesture";

            TrainedGesture previousSlideGesture = new TrainedGesture();
            previousSlideGesture.GestureActions.Add(slidePrevious);
            previousSlideGesture.GestureAlgorithms.Add(shakingLeftRight);
            previousSlideGesture.Name = "PreviousSlideGesture";
            
            TrainedGesture exitSlideGesture = new TrainedGesture();
            exitSlideGesture.GestureActions.Add(slideExit);
            exitSlideGesture.GestureAlgorithms.Add(roll);
            exitSlideGesture.Name = "ExitSlideGesture";
            #endregion

            #region Register GestureLib stuff
            //Register Algorithms
            _gestureLib.AvailableGestureAlgorithms.Add(shakingTopBottom);
            _gestureLib.AvailableGestureAlgorithms.Add(shakingLeftRight);
            _gestureLib.AvailableGestureAlgorithms.Add(roll);
            _gestureLib.AvailableGestureAlgorithms.Add(jab);
            _gestureLib.AvailableGestureAlgorithms.Add(pitch);

            //Register Actions
            _gestureLib.AvailableGestureActions.Add(slideNext);
            _gestureLib.AvailableGestureActions.Add(slidePrevious);
            _gestureLib.AvailableGestureActions.Add(slideLast);
            _gestureLib.AvailableGestureActions.Add(slideFirst);

            //Register Trained Gestures
            _gestureLib.TrainedGestures.Add(nextSlideGesture);
            _gestureLib.TrainedGestures.Add(previousSlideGesture);
            _gestureLib.TrainedGestures.Add(exitSlideGesture);

            _gestureLib.Recording.RecordingFinished += new EventHandler(Recording_RecordingFinished);
            #endregion

            niTray.Icon = Icon;
            _gestureLib.ScreenBounds = Screen.PrimaryScreen.Bounds;
            _gestureLib.ImpersonatingMouse = true;
        }

        private WiiGestureDevice CreateAndGetWiiDevice()
        {
            _wiimote = new Wiimote();
            _wiimote.Connect();
            _wiimote.SetReportType(Wiimote.InputReport.IRAccel, true);
            _wiimote.SetLEDs(false, true, true, false);

            //attach create WiiGestureDevice to GestureLib
            WiiGestureDevice wiiDevice = new WiiGestureDevice();
            wiiDevice.Dispatcher = null;
            wiiDevice.Wiimote = _wiimote;

            return wiiDevice;
        }

        private void Recording_RecordingFinished(object sender, EventArgs e)
        {
            GestureAlgorithmCollection gestures = _gestureLib.Recording.RecognizeRecording(_gestureLib.Recording.RecordedAccelerationGestureStates);
            TrainedGesture matchedTrainedGesture = _gestureLib.TrainedGestures.GetTrainedGestureByMatchedAlgorithms(gestures);

            if (matchedTrainedGesture != null)
            {
                matchedTrainedGesture.GestureActions.ExecuteAll();
            }
        }

        private void GlobalHotKeyHandler_HotkeyPressed(object sender, EventArgs e)
        {
            GlobalHotkeyHandler gh = (GlobalHotkeyHandler)sender;
            Debug.WriteLine(string.Format("Hotkey pressed: {0} {1}", gh.Key, gh.KeyModifiers));

            if (gh.Key == Keys.M && 
                (gh.KeyModifiers & GlobalHotkeyHandler.Modifiers.Control) == GlobalHotkeyHandler.Modifiers.Control && 
                (gh.KeyModifiers & GlobalHotkeyHandler.Modifiers.Alt) == GlobalHotkeyHandler.Modifiers.Alt)
            {
                _gestureLib.ImpersonatingMouse = !_gestureLib.ImpersonatingMouse;
                tsmiImpersonateMouse.Checked = !tsmiImpersonateMouse.Checked;
            }
        }

        #region Tray functionality
        private void OptionsForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!_isTrayClosing)
            {
                Hide();
                e.Cancel = true;
            }
        }

        private void tsmiClose_Click(object sender, EventArgs e)
        {
            _isTrayClosing = true;
            Close();
        }

        private void niTray_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (Visible)
            {
                Hide();
            }
            else
            {
                Show();
                Activate();
            }
        }

        private void OptionsForm_Shown(object sender, EventArgs e)
        {
            Hide();
            Opacity = 1;
        }
        #endregion
    }
}
